package com.whz.governance.redislimiter.config;

import com.google.common.collect.Lists;
import com.whz.generic.json.JacksonUtils;
import com.whz.governance.redislimiter.filter.RedisRateLimitFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.List;

/**
 * it works when in the servlet web and the StringRedisTemplate bean exits.
 *
 * @author whz
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(RedisRateLimiterProperties.class)
@ConditionalOnProperty(name = "generic.redis.rate-limiter.enable", havingValue = "true")
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class RedisRateLimiterConfiguration {

    public static final String[] A = new String[0];

    @Bean
    public FilterRegistrationBean<RedisRateLimitFilter> registerRedisRateLimitFilter(RedisRateLimiterProperties redisRateLimiterProperties) {
        Assert.notNull(redisRateLimiterProperties, "redisRateLimiterProperties cannot be null.");
        Assert.notEmpty(redisRateLimiterProperties.getConfig(), "config cannot be empty.");
        log.info("open rate limit filter,its config is :{}", JacksonUtils.toJsonString(redisRateLimiterProperties));

        List<String> urlPatterns = Lists.newLinkedList();
        redisRateLimiterProperties.getConfig().keySet().forEach(patter -> {
            urlPatterns.addAll(split(patter));
        });

        FilterRegistrationBean<RedisRateLimitFilter> registration = new FilterRegistrationBean<>();
        registration.addUrlPatterns(urlPatterns.toArray(A));
        registration.setFilter(new RedisRateLimitFilter(redisRateLimiterProperties));
        registration.setName("registerRedisRateLimitFilter");
        registration.setOrder(0);
        return registration;
    }

    private static List<String> split(String input) {
        return Arrays.asList(StringUtils.tokenizeToStringArray(input, ","));
    }
}